package biz

import (
	"time"

	"github.com/gin-gonic/gin"
	"gitlab1.moolink.net/trade/backend/gen"
	"lab.com/conf"
	"lab.com/consts"
	"lab.com/define/errorcode"
	"lab.com/gen/entity"
	"lab.com/request"
	"lab.com/utils"
)

type userBiz struct {
}

// User  用户
var User = userBiz{}

// Login 登录
func (user *userBiz) Login(c *gin.Context, req request.LoginInputReq) (res request.LoginRes, err error) {
	ctx := conf.Span(c, "biz user login", nil)
	userModel := conf.LabGen.User

	//根据phone获取用户信息
	info, err := userModel.WithContext(ctx).Where(userModel.Phone.Eq(req.Phone), userModel.Status.Eq(consts.UserStatusNormal)).First()
	if err != nil || info.ID == 0 {
		return res, errorcode.New(errorcode.ErrParams, "该手机号未注册，请核查", nil)
	}
	if info.Password != utils.Sha1En(req.Password+info.PasswordSalt) {
		return res, errorcode.New(errorcode.ErrParams, "密码错误", nil)
	}

	token, err := utils.GenerateToken(int(info.ID), info.Username)
	if err != nil {
		return res, err
	}

	//返回
	res.Token = token
	res.UserInfo.ID = info.ID
	res.UserInfo.Username = info.Username
	res.UserInfo.Phone = info.Phone
	res.UserInfo.Email = info.Email
	res.UserInfo.Avatar = info.Avatar
	res.UserInfo.Address = info.Address
	res.UserInfo.Gender = info.Gender
	res.UserInfo.GenderDesc = consts.GenderTypeDesc[int(info.Gender)]
	res.UserInfo.Status = info.Status
	res.UserInfo.IsUse = info.IsUse
	res.UserInfo.IsManager = info.IsManager
	res.UserInfo.Role = info.Role
	res.UserInfo.RoleName = consts.RoleTypeDesc[info.Role]
	res.UserInfo.Address = info.Address
	res.UserInfo.Subject = info.Subject
	res.UserInfo.Postion = info.Position
	res.UserInfo.CreateTime = info.CreateTime.Format("2006-01-02 15:04:05")
	res.UserInfo.UpdateTime = info.UpdateTime.Format("2006-01-02 15:04:05")
	res.UserInfo.Content = info.Content
	return res, nil
}

// ContentEdit 用户编辑自己的详细信息介绍
func (user *userBiz) ContentEdit(c *gin.Context, req request.ContentEditReq) (err error) {
	ctx := conf.Span(c, "biz user content edit", nil)
	userModel := conf.LabGen.User
	updateInfo := &entity.User{
		Content:    req.Content,
		UpdateTime: time.Now(),
	}

	_, err = userModel.WithContext(ctx).Select(userModel.UpdateTime, userModel.Content).
		Where(userModel.ID.Eq(req.UserID)).Updates(updateInfo)
	if err != nil {
		return err
	}
	return nil
}

// InfoUpdate 用户更新自己的信息
func (user *userBiz) InfoUpdate(c *gin.Context, req request.InfoUpdateReq) (err error) {
	ctx := conf.Span(c, "biz user info update", nil)
	userModel := conf.LabGen.User
	//检查手机号是否重复
	if req.Phone != "" {
		where := []gen.Condition{userModel.Phone.Eq(req.Phone), userModel.ID.Neq(req.UserID), userModel.Status.Eq(consts.UserStatusNormal)}
		var num int64
		num, err = userModel.WithContext(ctx).Where(where...).Count()
		if err != nil {
			return
		}
		if num != 0 {
			return errorcode.New(errorcode.ErrBizRecordDuplicate, "手机号已存在", nil)
		}
	}

	updateInfo := &entity.User{
		Username:   req.Username,
		Phone:      req.Phone,
		Gender:     req.Gender,
		Address:    req.Address,
		Avatar:     req.Avatar,
		Subject:    req.Subject,
		Email:      req.Email,
		Position:   req.Position,
		UpdateTime: time.Now(),
		// EnrollmentYear: req.EnrollmentYear,
	}

	_, err = userModel.WithContext(ctx).Select(userModel.UpdateTime, userModel.Gender, userModel.Avatar, userModel.Address,
		userModel.Subject, userModel.Email, userModel.Position, userModel.Username, userModel.Phone, userModel.EnrollmentYear).Where(userModel.ID.Eq(req.UserID)).Updates(updateInfo)
	if err != nil {
		return err
	}
	return nil
}

// Info 首页显示用户基本信息
func (user *userBiz) Info(c *gin.Context, req request.UserInfoReq) (res request.BasicUserInfo, err error) {
	ctx := conf.Span(c, "biz user info", nil)
	userModel := conf.LabGen.User

	info, err := userModel.WithContext(ctx).Where(userModel.ID.Eq(req.UserID)).First()
	if err != nil {
		return
	}

	res.ID = info.ID
	res.Username = info.Username
	res.Phone = info.Phone
	res.Email = info.Email
	res.Avatar = info.Avatar
	res.Gender = info.Gender
	res.GenderDesc = consts.GenderTypeDesc[int(info.Gender)]
	res.Status = info.Status
	res.IsUse = info.IsUse
	res.IsManager = info.IsManager
	res.Role = info.Role
	res.RoleName = consts.RoleTypeDesc[info.Role]
	res.Address = info.Address
	res.Subject = info.Subject
	res.CreateTime = info.CreateTime.Format("2006-01-02 15:04:05")
	res.UpdateTime = info.UpdateTime.Format("2006-01-02 15:04:05")
	res.Content = info.Content
	res.Position = info.Position
	res.EnrollmentYear = info.EnrollmentYear
	return
}

// List 首页显示用户列表
func (user *userBiz) List(c *gin.Context, req request.UserListReq) (res request.UserInfoList, err error) {
	ctx := conf.Span(c, "biz user list", nil)
	userModel := conf.LabGen.User

	where := []gen.Condition{userModel.Status.Eq(consts.UserStatusNormal)}
	if req.RoleID != 0 {
		where = append(where, userModel.Role.Eq(req.RoleID))
	}

	info, err := userModel.WithContext(ctx).Where(where...).Find()
	if err != nil {
		return
	}

	res.Count = len(info)
	res.List = make([]request.SimpleUserInfo, len(info))
	for i, info := range info {
		res.List[i] = request.SimpleUserInfo{
			ID:       info.ID,
			Username: info.Username,
			Avatar:   info.Avatar,
		}
	}
	return
}

// Add 新增用户
func (user *userBiz) Add(c *gin.Context, req request.UserAddReq) (err error) {
	ctx := conf.Span(c, "biz user add", nil)
	userModel := conf.LabGen.User

	// 手机号唯一
	if count, err := userModel.WithContext(ctx).Where(userModel.Phone.Eq(req.Phone), userModel.Status.Eq(consts.UserStatusNormal)).Count(); err != nil {
		return err
	} else if count > 0 {
		return errorcode.New(errorcode.ErrParams, "该手机号已注册，请核查", nil)
	}

	passwordSalt := utils.GetRandomBoth(6)
	info := &entity.User{
		Username:       req.Username,
		Phone:          req.Phone,
		PasswordSalt:   passwordSalt,
		Password:       utils.Sha1En(consts.DefaultPassword + passwordSalt),
		IsManager:      req.IsManager,
		IsUse:          req.IsUse,
		Role:           req.UserRole,
		CreateTime:     time.Now(),
		UpdateTime:     time.Now(),
		EnrollmentYear: req.EnrollmentYear,
	}
	err = userModel.WithContext(ctx).Create(info)
	return err
}

// ListInManage 用户管理页面显示
func (user *userBiz) ListInManage(c *gin.Context, req request.ListInManageReq) (res request.UserManageList, err error) {
	ctx := conf.Span(c, "biz user list in manage", nil)
	userModel := conf.LabGen.User

	where := []gen.Condition{userModel.Status.Eq(consts.UserStatusNormal)}
	if req.RoleID != 0 {
		where = append(where, userModel.Role.Eq(req.RoleID))
	}
	if req.Phone != "" {
		where = append(where, userModel.Phone.Eq(req.Phone))
	}
	if req.Username != "" {
		where = append(where, userModel.Username.Like("%"+req.Username+"%"))
	}

	info, count, err := userModel.WithContext(ctx).Where(where...).Order(userModel.IsManager.Desc()).FindByPage(req.Offset, req.Size)
	if err != nil {
		return
	}

	res.Count = int(count)
	res.List = make([]request.UserManageInfo, len(info))
	for i, info := range info {
		res.List[i] = request.UserManageInfo{
			ID:             info.ID,
			Username:       info.Username,
			Phone:          info.Phone,
			UserRole:       info.Role,
			IsUse:          info.IsUse,
			IsManager:      info.IsManager,
			EnrollmentYear: info.EnrollmentYear,
		}
	}
	return
}

// EditInManage 用户管理页面信息更改
func (user *userBiz) EditInManage(c *gin.Context, req request.EditInManageReq) (err error) {
	ctx := conf.Span(c, "biz user edit in manage", nil)
	userModel := conf.LabGen.User

	if count, err := userModel.WithContext(ctx).Where(userModel.Phone.Eq(req.Phone), userModel.ID.Neq(req.UserID),
		userModel.Status.Eq(consts.UserStatusNormal)).Count(); err != nil {
		return err
	} else if count > 0 {
		return errorcode.New(errorcode.ErrParams, "您修改的手机号已被他人注册，请核实", nil)
	}

	info := &entity.User{
		Username:       req.Username,
		Phone:          req.Phone,
		Role:           req.UserRole,
		IsUse:          req.IsUse,
		IsManager:      req.IsManager,
		EnrollmentYear: req.EnrollmentYear,
	}

	_, err = userModel.WithContext(ctx).Select(userModel.Username, userModel.Phone, userModel.Role,
		userModel.IsUse, userModel.IsManager, userModel.EnrollmentYear).Where(userModel.ID.Eq(req.UserID)).Updates(info)
	return
}

// IsUse 禁用/启用用户
func (user *userBiz) IsUse(c *gin.Context, req request.UserIsUseReq) (err error) {
	ctx := conf.Span(c, "biz user is use", nil)
	userModel := conf.LabGen.User
	_, err = userModel.WithContext(ctx).Where(userModel.ID.Eq(req.UserID)).Update(userModel.IsUse, req.IsUse)
	return err
}

// Delete 删除用户
func (user *userBiz) Delete(c *gin.Context, req request.UserDeleteReq) (err error) {
	ctx := conf.Span(c, "biz user delete", nil)
	userModel := conf.LabGen.User
	_, err = userModel.WithContext(ctx).Where(userModel.ID.Eq(req.UserID)).Update(userModel.Status, consts.UserStatusDelete)
	return err
}

// IsManager 为用户设置管理员
func (user *userBiz) IsManager(c *gin.Context, req request.UserIsManagerReq) (err error) {
	ctx := conf.Span(c, "biz user is manager", nil)
	userModel := conf.LabGen.User
	_, err = userModel.WithContext(ctx).Where(userModel.ID.Eq(req.UserID)).Update(userModel.IsManager, req.IsManager)
	return err
}

// PasswordReset 用户重置密码
func (user *userBiz) PasswordReset(c *gin.Context, req request.PasswordResetReq) (err error) {
	ctx := conf.Span(c, "biz user password reset", nil)
	userModel := conf.LabGen.User

	passwordSalt := utils.GetRandomBoth(6)
	info := &entity.User{
		PasswordSalt: passwordSalt,
		Password:     utils.Sha1En(consts.DefaultPassword + passwordSalt),
		UpdateTime:   time.Now(),
	}
	_, err = userModel.WithContext(ctx).Select(userModel.PasswordSalt, userModel.Password, userModel.UpdateTime).
		Where(userModel.ID.Eq(req.UserID)).Updates(info)
	return err
}

// PasswordEdit 用户修改密码
func (user *userBiz) PasswordEdit(c *gin.Context, req request.PasswordEditReq) (err error) {
	ctx := conf.Span(c, "biz user password edit", nil)
	userModel := conf.LabGen.User
	userInfo, err := userModel.WithContext(ctx).Where([]gen.Condition{userModel.ID.Eq(req.UserID)}...).First()
	if err != nil {
		return err
	}
	inputPassword := utils.Sha1En( req.OldPassword + userInfo.PasswordSalt)
	if inputPassword != userInfo.Password {
		return errorcode.New(errorcode.ErrParams, "旧密码错误", nil)
	}
	passwordSalt := utils.GetRandomBoth(6)
	info := &entity.User{
		PasswordSalt: passwordSalt,
		Password:     utils.Sha1En(req.NewPassword + passwordSalt),
		UpdateTime:   time.Now(),
	}
	_, err = userModel.WithContext(ctx).Select(userModel.PasswordSalt, userModel.Password, userModel.UpdateTime).
		Where(userModel.ID.Eq(req.UserID)).Updates(info)
	return err
}
